﻿using System;
using System.Collections.Generic;
using Fetches.Fetch.Dto;
using Fetches.Fetch.Fetcher;
using Fetches.Fetch.PagePool.Consume;
using Fetches.Fetch.Utils;

namespace Fetches.Fetch.Factory
{
    public abstract class AbstractFetchFactory:IFetchFactory
    {
        #region 工具方法

        public IList<long> GenFetcherIds(int count)
        {
            var result = new List<long>();
            for (var i = 1; i <= count; i++)
                result.Add(IdHelper.FetcherIdGenerator.GenerateId());

            return result;
        }

        #endregion
        #region 入库
        /// <summary>
        /// 开始按FetchOrder入库数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="order"></param>
        /// <returns></returns>
        public FetchReceipt Fetch<T>(FetchOrder order) where T : AbstractFetcher
        {
            order.FetcherTypeName = typeof(T).FullName;
            return ActuallyFetch(order); ;
        }

        /// <summary>
        /// 开始按FetchOrder入库数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="order"></param>
        /// <returns></returns>
        public FetchReceipt Fetch<T>(FetchOrder<T> order) where T : AbstractFetcher
        {
            return ActuallyFetch(order);
        }

        protected FetchTask FetchOrder2Task(FetchOrder order)
        {
            var fetcherIds = GenFetcherIds(order.FetcherCount);
            var task = new FetchTask
            {
                Id = IdHelper.FetchTaskIdGenerator.GenerateId(),
                FetchOrder = order,
                FetcherIds = fetcherIds
            };
            return task;
        }

        protected abstract FetchReceipt ActuallyFetch(FetchOrder order);
        

        #endregion

        #region 数据采集任务调整

        /// <summary>
        /// 加速入库，实际就是增加Fetcher
        /// </summary>
        /// <param name="receipt"></param>
        /// <param name="fetchers2Hire">考虑目标站情况，不建议增加太多</param>
        public abstract void SpeedUpFetch(FetchReceipt receipt, int fetchers2Hire);

        /// <summary>
        /// 减速入库，实际就是从FetcherIds中随机挑选几个Fetcher停掉
        /// </summary>
        /// <param name="receipt"></param>
        /// <param name="fetchers2Dismiss">要免职的fetcher数量只能小于当前任务的现有fetcher总数</param>
        public abstract void SpeedDownFetch(FetchReceipt receipt, int fetchers2Dismiss);

        /// <summary>
        /// 停止爬取入库
        /// </summary>
        /// <param name="receipt"></param>
        public abstract void StopFetch(FetchReceipt receipt);

        /// <summary>
        /// 继续入库，针对StopFetch
        /// </summary>
        /// <param name="receipt"></param>
        public abstract void ContinueFetch(FetchReceipt receipt);

        /// <summary>
        /// 由Factory主动通知回调函数爬取进度
        /// </summary>
        /// <param name="receipt"></param>
        /// <param name="progressAction"></param>
        /// <returns></returns>
        public abstract void Watch(FetchReceipt receipt, Action<FetchTaskProgress> progressAction);
        #endregion

        #region 数据加工

        /// <summary>
        /// 指定Processor，由工厂内部调度Processor消费
        /// </summary>
        /// <param name="processOrder">处理单中有入库的回执信息</param>
        /// <returns></returns>
        public abstract ProcessReceipt Process(ProcessOrder processOrder);

        /// <summary>
        /// 按照kafka的思路，可以以偏移来反复消费PagePool
        /// Consume方法是本地消费，Process方法是交给远程服务器消费
        /// </summary>
        /// <param name="receipt"></param>
        /// <returns></returns>
        public abstract PagePoolConsumer Consume(FetchReceipt receipt);
        #endregion
    }
}
